package org.geektimes.configuration.microprofile.config;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.spi.ConfigBuilder;
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 @author :   chuan
 @date :   2021/03/17
 */
public class DefaultConfigProviderResolver extends ConfigProviderResolver {

    private ConcurrentHashMap<ClassLoader, Config> configsRepository = new ConcurrentHashMap<>();

    private ClassLoader loadClassLoader(ClassLoader loader){
        return loader == null ? this.getClass().getClassLoader() : loader;
    }

    @Override
    public Config getConfig() {
        return getConfig(null);
    }

    @Override
    public Config getConfig(ClassLoader loader) {
        return configsRepository.computeIfAbsent(loader, this::newConfig);
    }

    private Config newConfig(ClassLoader loader) {
        return newConfigBuilder(loader).build();
    }

    @Override
    public ConfigBuilder getBuilder() {
        return newConfigBuilder(null);
    }

    private ConfigBuilder newConfigBuilder(ClassLoader loader) {
        return new DefaultConfigBuilder(loadClassLoader(loader));
    }

    @Override
    public void registerConfig(Config config, ClassLoader classLoader) {
        configsRepository.put(classLoader, config);
    }

    @Override
    public void releaseConfig(Config config) {
        List<ClassLoader> keys = new LinkedList<>();

        for (Map.Entry<ClassLoader, Config> configEntry : configsRepository.entrySet()) {
            if (Objects.equals(configEntry.getValue(), config)){
                keys.add(configEntry.getKey());
            }
        }
        keys.forEach(configsRepository::remove);
    }
}
